﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace FunctionGraph
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

        Bitmap buffer;
        Renderer curRenderer;
        BinaryCodeEvaluator[] curEvals;


        private void btnDraw_Click(object sender, EventArgs e)
        {
            var code = Compiler.Compile(txtEquation.Text);
            if (code == null)
            {
                txtEquation.ForeColor = Color.Red;
            }
            else
            {
               // try
                {
                    paused = true;
                    cancellation.Cancel();
                    SyncRefineThread();
                    
                    BinaryCodeEvaluator[] evals = new BinaryCodeEvaluator[16];
                    for (int i = 0; i < evals.Length; i++)
                        evals[i] = new BinaryCodeEvaluator(code.MainCode, code.SolutionEvaluationTree);
                    var renderer = new Renderer(buffer.Width, buffer.Height);
                    renderer.OffsetX = -256;
                    renderer.OffsetY = -256;
                    renderer.Draw(buffer, evals);
                    txtEquation.ForeColor = Color.Black;
                    pnlContent.Refresh();
                    curEvals = evals;
                    curRenderer = renderer;
                    paused = false;
                }
               // catch (Exception)
                {
 
                }
            }
        }

        ManualResetEvent refineEvent = new ManualResetEvent(true);
        ManualResetEvent refineThreadTerminate = new ManualResetEvent(false);
        bool refineThreadRunning = true;
        private void SyncRefineThread()
        {
            refineEvent.WaitOne();
        }

        bool shouldUpdate = false;
        bool paused = false;
        CancellationTokenSource cancellation = new CancellationTokenSource();
        private void RefineThread()
        {
            while (refineThreadRunning)
            {
                if (!paused && curRenderer != null && !curRenderer.Finished)
                {
                    refineEvent.Reset();
                    cancellation = new CancellationTokenSource();
                    curRenderer.Refine(curEvals, cancellation.Token);
                    shouldUpdate = true;
                }
                else
                    Thread.Sleep(50);
                refineEvent.Set();
            }
            refineThreadTerminate.Set();
        }


        private void MainForm_Load(object sender, EventArgs e)
        {
            buffer = new Bitmap(512, 512);
            new Thread(RefineThread).Start();
            
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            refineThreadRunning = false;
            refineThreadTerminate.WaitOne();
            buffer.Dispose();
        }

        private void pnlContent_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.DrawImageUnscaled(buffer, 0, 0);
        }

        private void tmrUpdate_Tick(object sender, EventArgs e)
        {
            if (shouldUpdate && curRenderer!=null)
            {
                shouldUpdate = false;
                curRenderer.Flush(buffer);
                pnlContent.Refresh();
            }
        }

    }
}
